NLP Data Augmentation 常見方法


Posted by Mars.Su on 2020-10-26

Abstract

過往我們都知道當資料量不足時,硬著頭皮去訓練機器學習模型,反而會帶來不好的效果。所以後來有人提出了Data Augmentation的概念,為了就是應用於資料不足時,可以透過一些方法來將資料做增量的動作,進而能進一步的應用於模型的訓練。

過往如果在圖片的data augmentation,時常會利用旋轉、偏移、縮放等方式,進而增加資料。而data augmentation其實最普遍用在影像處理的領域,所以對於NLP的相關方法可說是少之又少,包含現在最新的NLP data Augmentaion方法的論文是Conditional Bert Contextual Augmentation(Xing et al., 2018),而這篇我也會在下一篇文章來進一步的說明。

其中主要參考了來源是一位國外的工程師Amit Chaudhary的分享,我也有加入一些簡中的作法進來,希望能幫助到大家

Introduction

這篇我會先以比較簡單且傳統的做法來做NLP Data Augmentation介紹,其中我會盡可能以『中文』來舉例說明,這樣對於中文語系的國家看到時也會比較直覺,常見方法如下:

一、相似詞替換

概念:
我想這個方法是大家最直覺想到的作法,就是利用相近意思的詞彙來做代替,如下圖

常見做法:

  1. 建立分詞WordNet
    如果是本身就有著大量的文字資料時,可以透過分詞(ex. Jieba, 中研院CKIP繁中斷詞)後的結果以及GraphDB(ex. Neo4J, Dgraph, AWS-Naptune)等相關工具來儲存,再利用一些演算法來計算相似詞之間的權重即可找出相似詞。

    當然如果採用這個方式,無論是建置或是維護的成本就會相對比較高一點,但卻是有機會可以建立自己產業know-how的WordNet。除此之外,如果是要做contextual的話,有些詞是一詞多義的,所以如果搭配上下文的話該方法會有一定的限制。

  2. 建立詞向量模型來計算相近詞
    該方法就可以利用像是Word2vec的model來計算(ex. gensim)來將詞匯入,其中內部會透過像是cosine-similarity方法來計算相近詞,再由自己決定要取Top N 的詞來替換原本的字詞做取代。下面是一個簡單的程式示意,如果有不熟悉gensim怎麼操作的話,可以參考這篇文件

from gensim.models import word2vec

model = word2vec.Word2Vec.load('word2vec.model')
for item in model.most_similar('帥氣'):
    print(item)
結果如下
('英俊', 0.7148515)
('酷帥', 0.7018151)
('俊朗', 0.6905148)

二、Back Translation(反向翻譯)

概念:
這個方法是透過將原本句子所屬的語言翻譯到另外一個語言,在轉回來取得句子。
簡單來說,今天有一句話"小明很帥氣"(中文),先翻譯到英文變成"Xiao Ming is handsome",然後再翻回來中文結果變成"小明很帥",我們就可以拿到意思一樣但表達不同的語句,所以可以自行決定要翻英文再回來中文、或翻其他國外語言再回來中文都可以。該方法的簡單示意圖如下:

這邊引用一下國外有一位工程師的作法,他就是將句子翻譯到多國語言再翻回來做資料增量,示意圖如下

常見做法:
這個方法最常見就是去呼叫一隻translate api(ex.google-translate-api)然後再將結果蒐集到原本的資料集當中,來進行資料增量。

三、Random Noise Injection

該方式透過加入noise的資料來加強,進而增加模型的robustness

概念:
接下來介紹的概念是來自Easy Data Augmentation(Wei et al., 2019),簡單來說就是新增刪除修改一些雜訊資料進來做訓練,簡中的範例github連結請點此

  1. Random Insert
    找一個相似詞隨機插入到句子中的隨機位置,如下圖
  2. Random Swap
    隨機交換句子中任兩個word的位置且重複n次,如下圖
  3. Random Delete
    依照一個機率P隨機刪除句子中某一個word,如下圖

四、Syntax-tree

概念:
其實這個方法概念不難,但是技術要做到的話可能會有點困難度,尤其是在中文的語系。簡單來說,他就是將主動的語法轉變成被動的語法,或是將被動轉換成主動的語法,以下面的示意圖呈現:

藉由上面的範例可以知道,即便將主詞與受詞做對掉(主動換被動),整體的句子語意不會因此而有所不一樣。

但這個方式實作上比較麻煩,第一並不是全部的語句可以這樣被轉換;第二,即便可以轉換在中文文字的轉換上會有點麻煩,我也相信這個方法可以做到一定程度的增量,所以也把他列出來讓大家知道它的原理。

五、Pretrained model MLM(Masked Language model)

概念:
接下來這邊開始會簡單說明一下關於pretrained model的作法,前面幾個作法通常只要搞定好整體架構的IPO(Input, Process, Ouput)就可以將新增的資料合併到原本的資料集來做到『增量』的效果。

但其實很多時候我們手邊並沒有太多的corpus或文字相關的資料,有時候在一些技術跟時間成本的考量會採用到事先訓練好的ML模型,像是Bert, AlBert等,透過此方法來適時的站在巨人的肩膀上來降低一點自己的門檻。

我們都知道以BERT來說,他會先經歷過兩個pre-train的方法,一個NSP(Next Setence Prediction)來預測這一句是否為上一句的下一句,以及另一個是 MLM(Masked Language model)透過前後鄰近的詞用來做被mask的詞預測。因此在這裡利用的MLM的特型把其中一個詞替換成[mask]來讓已經pretrain好的模型來做預測該詞。

實際做法:
關於怎麼做,我們可以自己找一個的詞,並將他替換成[mask],接著利用pretrain model來預測他有可能會出現的詞,可以利用HuggingFace這個套件來處理,它提供了許多NLP Pretrained model還有一些api的操作方法,相信使用起來並不會太難。簡單的程式範例如下:

from transformers import pipeline
nlp = pipeline('fill-mask')
nlp('小明 <mask> 帥氣')
結果示意如下
[{'score': 0.515411913394928,
  'sequence': '<s> 小明 非常 帥氣</s>',
  'token': 1256},
 {'score': 0.1166248694062233,
  'sequence': '<s> 小明 很 帥氣</s>',
  'token': 269},
 {'score': 0.07387523353099823,
  'sequence': '<s> 小明 超級 帥氣</s>',
  'token': 2422}
 ]

六、Conditional Pretrained model

這個方法來自Data Augmentation using Pre-trained Transformer Models(Kumar et al., 2020),簡單來說他將每一句的打上一個label,並且concat進入到transformer做訓練,示意圖如下

而這個方法的fine-tune就是文字生成,進而來生成新樣本,至於如何生成呢?可以透過指定前n個字詞,來讓model針對接下來的字詞做預測,示意如下:

以這個例子來說,就是給定好label(positiver)跟前三個字詞('it is very'),接著就可以讓pretrain model來做預測且生成句子,也能確保整體語句的意義不會不同。

Conclusion

當然從一些參考資料當中也有一些其他的簡單方式可以做到文字的data augmentation,這邊提出自己認為比較重要且用過的方式,以及認為比較適合在中文這個語系的做分享,之後若有機會用到其中幾個方法,像是Mixup等再來補充這篇文章的內容。

最後,近年來也有學者提出了幾篇論文來探討關於文字的Data Augmentaion,其連結如下供大家參考,接下來也會陸續讀完這幾篇論文來分享:

Reference


#AI #NLP #Data-Augmentation #Paper







Related Posts

利用 Elm 製作 Chrome Extension

利用 Elm 製作 Chrome Extension

Node.appendChild() vs. Element.append()

Node.appendChild() vs. Element.append()

1045. Customers Who Bought All Products

1045. Customers Who Bought All Products


Comments